﻿/*=============================================================================
* File Name : Quaternion.h                         Ver : 1.00  Date : 2009-3-25
*
* Description :
*
*       クォータニオン計算　ヘッダ
*
* Author : 土田　悠貴.
*============================================================================*/
#ifndef _QUATERNION_H_
#define _QUATERNION_H_

namespace tglib
{

class Vector3;
class Matrix3;
class Matrix4;

/**
 * @brief クォータニオン計算クラス．
 */
class Quaternion
{
public:
	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 */
	Quaternion();

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]  X x成分．
	 * @param [in]  Y y成分．
	 * @param [in]  Z z成分．
	 * @param [in]  W w成分．
	 */
	Quaternion( float X, float Y, float Z, float W );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]  angle 角度．
	 * @param [in]  axis  xyz成分．
	 */
	Quaternion( float angle, const Vector3& axis );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]  m 3行3列の行列．
	 */
	Quaternion( const Matrix3& m );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]  m 4行4列の行列．
	 */
	Quaternion( const Matrix4& m );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]  axisX X軸の位置．
	 * @param [in]  axisY Y軸の位置．
	 * @param [in]  axisZ Z軸の位置．
	 */
	Quaternion( const Vector3& axisX, const Vector3& axisY, const Vector3& axisZ );

	/*===========================================================================*/
	/**
	 * 単位クォータニオン化する．
	 *
	 * @return 単位クォータニオン ．
	 */
	Quaternion& identity();

	/*===========================================================================*/
	/**
	 * 内積を求める．
	 *
	 * @param [in]  q クォータニオン ．
	 * @return 内積を返す ．
	 */
	float dot( const Quaternion& q ) const;

	/*===========================================================================*/
	/**
	 * 長さを求める．
	 *
	 * @return 長さを返す ．
	 */
	float length() const;

	/*===========================================================================*/
	/**
	 * クォータニオンを正規化する．
	 *
	 * @return 正規化したクォータニオン ．
	 */
	Quaternion& normalize();

	/*===========================================================================*/
	/**
	 * 逆クォータニオン化する．
	 *
	 * @return 逆クォータニオン ．
	 */
	Quaternion& inverse();

	/*===========================================================================*/
	/**
	 * 正規化したクォータニオンを取得する．
	 *
	 * @return 正規化したクォータニオン ．
	 */
	Quaternion getNormalized() const;

	/*===========================================================================*/
	/**
	 * 逆クォータニオンを取得．
	 *
	 * @return 逆クォータニオン ．
	 */
	Quaternion getInverse() const;

	/*===========================================================================*/
	/**
	 * 回転角度からクォータニオンを設定．
	 *
	 * @param [in]  angle 回転角度 ．
	 * @param [in]  vx 回転軸のx成分 ．
	 * @param [in]  vy 回転軸のy成分 ．
	 * @param [in]  vz 回転軸のz成分 ．
	 * @return クォータニオン ．
	 */
	Quaternion& setRotate( float angle, float vx, float vy, float vz );

	/*===========================================================================*/
	/**
	 * 回転角度からクォータニオンを設定．
	 *
	 * @param [in]  angle 回転角度 ．
	 * @param [in]  axis  回転軸 ．
	 * @return クォータニオン ．
	 */
	Quaternion& setRotate( float angle, const Vector3& axis );

	/*===========================================================================*/
	/**
	 * 回転角度からクォータニオンを設定．
	 *
	 * @param [in]  yaw   ヨー ．
	 * @param [in]  pitch ピッチ ．
	 * @param [in]  roll  ロール ．
	 * @return クォータニオン ．
	 */
	Quaternion& setRoteteYawPitchRoll( float yaw, float pitch, float roll );

	/*===========================================================================*/
	/**
	 * 回転行列を設定．
	 *
	 * @param [in]  m 回転行列 ．
	 * @return クォータニオン ．
	 */
	Quaternion& setMatrix( const Matrix3& m );

	/*===========================================================================*/
	/**
	 * 回転行列を設定．
	 *
	 * @param [in]  m 回転行列 ．
	 * @return クォータニオン ．
	 */
	Quaternion& setMatrix( const Matrix4& m );

	/*===========================================================================*/
	/**
	 * 軸を取得．
	 *
	 * @return 回転軸 ．
	 */
	Vector3 getAxis() const;

	/*===========================================================================*/
	/**
	 * 角度を取得．
	 *
	 * @return 角度 ．
	 */
	float getAngle() const;

	/*===========================================================================*/
	/**
	 * ヨーを取得．
	 *
	 * @return ヨー ．
	 */
	float getYaw() const;

	/*===========================================================================*/
	/**
	 * 、ピッチを取得．
	 *
	 * @return ピッチ ．
	 */
	float getPitch() const;

	/*===========================================================================*/
	/**
	 * ロールを取得．
	 *
	 * @return ロール ．
	 */
	float getRoll() const;

	/*===========================================================================*/
	/**
	 * 球面線形補間．
	 *
	 * @param [in]  q1 クォータニオン ．
	 * @param [in]  q2 クォータニオン ．
	 * @param [in]  t 補間値 ．
	 * @return 補間されたクォータニオン ．
	 */
	Quaternion& slerp( const Quaternion& q1, const Quaternion& q2, float t );

	/*===========================================================================*/
	/**
	 * 線形補間を行う．
	 *
	 * @param [in]  q1 クォータニオン ．
	 * @param [in]  q2 クォータニオン ．
	 * @param [in]  t 補間値 ．
	 * @return 補間されたクォータニオン ．
	 */
	Quaternion& lerp( const Quaternion& q1, const Quaternion& q, float t );

	/*===========================================================================*/
	/**
	 * (+)単項演算子オーバーロード．
	 *
	 * @return 結果のQuaternion．
	 */
	Quaternion operator + () const;

	/*===========================================================================*/
	/**
	 * (-)単項演算子オーバーロード．
	 *
	 * @return 結果のQuaternion．
	 */
	Quaternion operator - () const;

	/*===========================================================================*/
	/**
	 * (+=) 演算子オーバーロード．
	 * 
	 * @param [in]  q Quaternion．
	 * @return 結果のQuaternion．
	 */
	Quaternion& operator += ( const Quaternion& q );

	/*===========================================================================*/
	/**
	 * (-=) 演算子オーバーロード．
	 * 
	 * @param [in]  q Quaternion．
	 * @return 結果のQuaternion．
	 */
	Quaternion& operator -= ( const Quaternion& q );

	/*===========================================================================*/
	/**
	 * (*=) 演算子オーバーロード．
	 * 
	 * @param [in]  q Quaternion．
	 * @return 結果のQuaternion．
	 */
	Quaternion& operator *= ( const Quaternion& q );

	/*===========================================================================*/
	/**
	 * (*=) 演算子オーバーロード．
	 * 
	 * @param [in]  s スカラー．
	 * @return 結果のQuaternion．
	 */
	Quaternion& operator *= ( float s );

	/*===========================================================================*/
	/**
	 * (/=) 演算子オーバーロード．
	 * 
	 * @param [in]  s スカラー．
	 * @return 結果のQuaternion．
	 */
	Quaternion& operator /= ( float s );

public:
	/** @brief x成分 */
	float x;	

	/** @brief y成分 */
	float y;	

	/** @brief z成分 */
	float z;	

	/** @brief 回転角度 */
	float w;	
};

/***  以下非メンバ関数 *******************************************************/

/*===========================================================================*/
/**
 * (+)演算子オーバーロード．
 * 
 * @param [in]  q1 Quaternion．
 * @param [in]  q2 Quaternion．
 * @return 結果のQuaternion．
 */
const Quaternion operator + ( const Quaternion& q1, const Quaternion& q2 );

/*===========================================================================*/
/**
 * (-)演算子オーバーロード．
 * 
 * @param [in]  q1 Quaternion．
 * @param [in]  q2 Quaternion．
 * @return 結果のQuaternion．
 */
const Quaternion operator - ( const Quaternion& q1, const Quaternion& q2 );

/*===========================================================================*/
/**
 * (*)演算子オーバーロード．
 * 
 * @param [in]  q1 Quaternion．
 * @param [in]  q2 Quaternion．
 * @return 結果のQuaternion．
 */
const Quaternion operator * ( const Quaternion& q1, const Quaternion& q2 );

/*===========================================================================*/
/**
 * (*)演算子オーバーロード．
 * 
 * @param [in]  q1 Quaternion．
 * @param [in]  s スカラー．
 * @return 結果のQuaternion．
 */
const Quaternion operator * ( const Quaternion& q, float s );

/*===========================================================================*/
/**
 * (*)演算子オーバーロード．
 * 
 * @param [in]  s スカラー．
 * @param [in]  q1 Quaternion．
 * @return 結果のQuaternion．
 */
const Quaternion operator * ( float s, const Quaternion& q );

/*===========================================================================*/
/**
 * (/)演算子オーバーロード．
 * 
 * @param [in]  q1 Quaternion．
 * @param [in]  s スカラー．
 * @return 結果のQuaternion．
 */
const Quaternion operator / ( const Quaternion& q, float s );

/*===========================================================================*/
/**
 * (==) 演算子オーバーロード．
 * 
 * @param [in]  q1 Quaternion．
 * @param [in]  q2 Quaternion．
 * @return 比較結果．
 */
bool operator == ( const Quaternion& q1, const Quaternion& q2 );

/*===========================================================================*/
/**
 * (!=) 演算子オーバーロード．
 * 
 * @param [in]  q1 Quaternion．
 * @param [in]  q2 Quaternion．
 * @return 比較結果．
 */
bool operator != ( const Quaternion& q1, const Quaternion& q2 );


} // namespace tglib

#endif

/*========= End of File =====================================================*/
